<script setup lang="ts">
import { reactive, ref, watch, computed } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import { ElMessage } from "element-plus";
import type {
  CreateRecordPayload,
  CreateRecipientPayload
} from "@/api/system/notify/record";
import type { TemplateItem } from "@/api/system/notify/template";

interface TemplateOption {
  id: number;
  name: string;
  type: string;
}

interface RecipientRow {
  key: number;
  target_type: string;
  target_id: string | number;
  channel: string;
}

interface Props {
  templates: TemplateOption[];
  channelOptions: string[];
  onSubmit?: (payload: CreateRecordPayload) => Promise<void>;
  loadTemplate?: (id: number) => Promise<TemplateItem>;
}

const props = defineProps<Props>();

const formRef = ref<FormInstance>();
const submitting = ref(false);
const templateLoading = ref(false);
const keySeed = ref(1);
const selectedTemplate = ref<TemplateItem | null>(null);
const selectedTemplateType = ref<string>("");

const CHANNEL_LABELS: Record<string, string> = {
  websocket: "WebSocket",
  wechat: "微信",
  sms: "短信",
  email: "邮箱",
  dingtalk: "钉钉",
  dingtalk_work: "钉钉",
  dingTalk: "钉钉",
  lark: "飞书",
  feishu: "飞书",
  app: "App",
  push: "推送",
  system: "系统"
};

const baseChannelOptions = computed(() =>
  props.channelOptions && props.channelOptions.length > 0
    ? props.channelOptions
    : ["websocket", "sms", "email"]
);

const selectedTemplateChannels = computed(() => {
  const template = selectedTemplate.value;
  if (!template || !template.channels) return [];
  const entries = Object.entries(template.channels);
  return entries
    .map(([channel, config]) => ({
      channel,
      enabled: config?.enabled === undefined ? true : Boolean(config?.enabled),
      route: config?.route ?? ""
    }))
    .filter(item => item.enabled);
});

const effectiveChannelOptions = computed(() => {
  const templateChannels = selectedTemplateChannels.value;
  if (templateChannels.length > 0) {
    return templateChannels.map(item => item.channel);
  }
  return baseChannelOptions.value;
});

const defaultChannel = computed(
  () => effectiveChannelOptions.value[0] ?? "websocket"
);

const formModel = reactive({
  template_id: null as number | null,
  title: "",
  content: "",
  payloadText: "",
  route: "",
  recipients: [
    {
      key: keySeed.value++,
      target_type: "user",
      target_id: "",
      channel: defaultChannel.value
    }
  ] as RecipientRow[]
});

const rules: FormRules<typeof formModel> = {
  title: [{ required: true, message: "请输入通知标题", trigger: "blur" }],
  content: [{ required: true, message: "请输入通知内容", trigger: "blur" }]
};

const templateOptions = computed(() => props.templates ?? []);

const channelLabel = (channel: string) => {
  const key = channel?.toString?.().toLowerCase() ?? "";
  return CHANNEL_LABELS[key] ?? CHANNEL_LABELS[channel] ?? channel ?? "-";
};

const templateChannelInfo = computed(() =>
  selectedTemplateChannels.value.map(item => ({
    ...item,
    label: channelLabel(item.channel)
  }))
);

const syncRecipientsWithTemplate = (
  template: TemplateItem | null,
  forceRoute = false
) => {
  if (!template) return;
  const available = selectedTemplateChannels.value.map(item => item.channel);
  if (available.length === 0) return;

  formModel.recipients.forEach(rec => {
    if (!available.includes(rec.channel)) {
      rec.channel = available[0];
    }
  });

  const routeCandidate = selectedTemplateChannels.value
    .map(item => item.route)
    .find(route => route && String(route).trim() !== "");
  if (routeCandidate && (forceRoute || !formModel.route)) {
    formModel.route = String(routeCandidate);
  }
};

watch(
  () => effectiveChannelOptions.value,
  options => {
    if (!options || options.length === 0) return;
    formModel.recipients.forEach(rec => {
      if (!options.includes(rec.channel)) {
        rec.channel = options[0];
      }
    });
  },
  { immediate: true }
);

const addRecipient = () => {
  formModel.recipients.push({
    key: keySeed.value++,
    target_type: "user",
    target_id: "",
    channel: defaultChannel.value
  });
};

const removeRecipient = (row: RecipientRow) => {
  if (formModel.recipients.length === 1) {
    ElMessage.warning("至少需要一个接收人");
    return;
  }
  const index = formModel.recipients.findIndex(item => item.key === row.key);
  if (index !== -1) {
    formModel.recipients.splice(index, 1);
  }
};

const parsePayload = () => {
  const text = formModel.payloadText?.trim();
  if (!text) return null;
  try {
    return JSON.parse(text);
  } catch (error: any) {
    throw new Error(error?.message ?? "JSON 格式不正确");
  }
};

const normalizeRecipients = (): CreateRecipientPayload[] => {
  const recipients: CreateRecipientPayload[] = [];
  for (const row of formModel.recipients) {
    const type = String(row.target_type ?? "").trim();
    const id = row.target_id;
    const channel = String(row.channel ?? "").trim();

    if (!type) {
      throw new Error("接收人类型不能为空");
    }
    if (id === "" || id === null || id === undefined) {
      throw new Error("接收人ID不能为空");
    }

    if (!/^\d+$/.test(String(id))) {
      throw new Error("接收人ID必须为正整数");
    }
    if (!channel) {
      throw new Error("请选择接收渠道");
    }

    const numericId = Number(id);

    recipients.push({
      target_type: type,
      target_id: numericId,
      channel
    });
  }

  if (recipients.length === 0) {
    throw new Error("请至少添加一名接收人");
  }

  return recipients;
};

const applyTemplate = async (id: number) => {
  if (!props.loadTemplate) return;
  templateLoading.value = true;
  try {
    const template = await props.loadTemplate(id);
    if (template) {
      selectedTemplate.value = template;
      selectedTemplateType.value = template.type ?? "";
      formModel.title = template.title ?? "";
      formModel.content = template.content ?? "";
      syncRecipientsWithTemplate(template, true);
    }
  } catch (error: any) {
    ElMessage.error(error?.message ?? "加载模板失败");
  } finally {
    templateLoading.value = false;
  }
};

watch(
  () => formModel.template_id,
  newValue => {
    if (newValue && newValue > 0) {
      selectedTemplate.value = null;
      const option = templateOptions.value.find(item => item.id === newValue);
      selectedTemplateType.value = option?.type ?? "";
      applyTemplate(newValue);
    } else {
      selectedTemplate.value = null;
      selectedTemplateType.value = "";
    }
  }
);

const submitForm = async () => {
  try {
    await formRef.value?.validate();
  } catch {
    return false;
  }

  if (!props.onSubmit) {
    return true;
  }

  let payloadData: Record<string, any> | null;
  try {
    payloadData = parsePayload();
  } catch (error: any) {
    ElMessage.error(error?.message ?? "附加数据格式错误");
    return false;
  }

  let recipients: CreateRecipientPayload[];
  try {
    recipients = normalizeRecipients();
  } catch (error: any) {
    ElMessage.error(error?.message ?? "请检查接收人信息");
    return false;
  }

  const payload: CreateRecordPayload = {
    template_id: formModel.template_id || undefined,
    template_type:
      selectedTemplate.value?.type ??
      (selectedTemplateType.value ? selectedTemplateType.value : undefined),
    title: formModel.title.trim(),
    content: formModel.content,
    data: payloadData ?? undefined,
    payload: payloadData ?? undefined,
    recipients,
    route: formModel.route.trim() || undefined
  };

  submitting.value = true;
  try {
    await props.onSubmit(payload);
    return true;
  } catch (error: any) {
    ElMessage.error(error?.message ?? "创建通知失败");
    return false;
  } finally {
    submitting.value = false;
  }
};

defineExpose({ submitForm });
</script>

<template>
  <div v-loading="submitting || templateLoading" class="notify-record-form">
    <el-form
      ref="formRef"
      :model="formModel"
      :rules="rules"
      label-width="110px"
      class="record-form"
    >
      <el-form-item label="选择模板">
        <div class="template-select">
          <el-select
            v-model="formModel.template_id"
            filterable
            clearable
            placeholder="可选，选择模板将自动填充标题与内容"
            class="template-select__picker"
          >
            <el-option
              v-for="item in templateOptions"
              :key="item.id"
              :label="item.name ? `${item.name} (${item.type})` : item.type"
              :value="item.id"
            />
          </el-select>
          <div v-if="selectedTemplate" class="template-select__info">
            <div class="template-select__title">
              {{ selectedTemplate.name || selectedTemplate.type }}
            </div>
            <div class="template-select__meta">
              <span class="template-select__meta-item">
                类型：{{ selectedTemplate.type || "-" }}
              </span>
              <span
                v-if="selectedTemplate.category"
                class="template-select__meta-item"
              >
                分类：{{ selectedTemplate.category }}
              </span>
            </div>
            <div
              v-if="templateChannelInfo.length"
              class="template-select__channels"
            >
              <span class="template-select__channels-label">可用渠道：</span>
              <el-space wrap :size="6">
                <el-tag
                  v-for="item in templateChannelInfo"
                  :key="item.channel"
                  size="small"
                  effect="plain"
                >
                  {{ item.label }}
                  <span v-if="item.route" class="template-select__route">
                    · {{ item.route }}
                  </span>
                </el-tag>
              </el-space>
            </div>
            <div
              v-if="selectedTemplate.description || selectedTemplate.remark"
              class="template-select__description"
            >
              {{ selectedTemplate.description || selectedTemplate.remark }}
            </div>
            <el-input
              class="template-select__content"
              :model-value="selectedTemplate.content"
              type="textarea"
              :rows="3"
              readonly
              placeholder="模板内容"
            />
          </div>
        </div>
      </el-form-item>
      <el-form-item label="通知标题" prop="title">
        <el-input v-model.trim="formModel.title" placeholder="请输入通知标题" />
      </el-form-item>
      <el-form-item label="通知内容" prop="content">
        <el-input
          v-model="formModel.content"
          type="textarea"
          :rows="5"
          placeholder="请输入通知内容，可使用模板占位符"
        />
      </el-form-item>
      <el-form-item label="变量数据">
        <el-input
          v-model="formModel.payloadText"
          type="textarea"
          :rows="4"
          placeholder="可选，JSON 格式，用于模板占位符或附加参数"
        />
      </el-form-item>
      <el-form-item label="跳转路由">
        <el-input
          v-model.trim="formModel.route"
          placeholder="可选，通知点击后跳转路径/URL"
        />
      </el-form-item>
      <el-form-item label="接收人列表" required>
        <div class="recipient-table">
          <div
            v-for="recipient in formModel.recipients"
            :key="recipient.key"
            class="recipient-row"
          >
            <el-select
              v-model="recipient.target_type"
              filterable
              allow-create
              default-first-option
              placeholder="类型，如 user/org"
              class="recipient-row__type"
            >
              <el-option label="用户(user)" value="user" />
              <el-option label="组织(org)" value="org" />
              <el-option label="角色(role)" value="role" />
            </el-select>
            <el-input
              v-model="recipient.target_id"
              placeholder="接收人ID"
              class="recipient-row__id"
            />
            <el-select
              v-model="recipient.channel"
              placeholder="渠道"
              class="recipient-row__channel"
            >
              <el-option
                v-for="item in effectiveChannelOptions"
                :key="item"
                :label="channelLabel(item)"
                :value="item"
              />
            </el-select>
            <el-button type="danger" link @click="removeRecipient(recipient)">
              删除
            </el-button>
          </div>
          <el-button type="primary" text @click="addRecipient">
            + 新增接收人
          </el-button>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>

<style scoped>
.notify-record-form {
  padding: 8px 4px;
}

.recipient-table {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.recipient-row {
  display: flex;
  gap: 8px;
  align-items: center;
  width: 100%;
}

.recipient-row__type {
  width: 140px;
}

.recipient-row__id {
  flex: 1;
}

.recipient-row__channel {
  width: 160px;
}

.template-select {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

.template-select__picker {
  width: 100%;
}

.template-select__info {
  padding: 12px;
  border: 1px solid var(--el-border-color-light);
  border-radius: 8px;
  background-color: var(--el-fill-color-light);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.template-select__title {
  font-size: 14px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.template-select__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  color: var(--el-text-color-secondary);
  font-size: 13px;
}

.template-select__channels {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  font-size: 13px;
}

.template-select__channels-label {
  color: var(--el-text-color-secondary);
}

.template-select__route {
  margin-left: 4px;
  color: var(--el-text-color-secondary);
  font-size: 12px;
}

.template-select__description {
  font-size: 13px;
  color: var(--el-text-color-secondary);
  line-height: 1.5;
}

.template-select__content :deep(textarea) {
  font-family: var(--el-font-family);
  background-color: #fff;
}
</style>
